package lab.poc.erl.showcase.timer;

import java.util.List;

import lab.poc.erl.Actor;
import lab.poc.erl.After;
import lab.poc.erl.MatchOrAfter;
import lab.poc.erl.Pattern;

/**
 * A simplistic actor-based Timer.
 */
final class PeriodicTimer extends Actor {

	static final Object CANCEL = new Object();

	public PeriodicTimer() {
		// package-private actors need explicitly
		// declared public no-arg constructor
	}

	@Override
	protected void onSpawn(final List<Object> args) {
		long period = (Long) args.get(0);
		After<?> command = (After<?>) args.get(1);

		loop(period, command);
	}

	private void loop(long period, final After<?> command) {
		boolean accept = true;
		while (accept) {
			MatchOrAfter<?> m = receiveWithTimeout(period, command,
					CancelMessage.PATTERN);
			if (m.isMatch()) {
				accept = false;
			}
		}
	}

	private static final class CancelMessage implements Pattern {
		static final CancelMessage PATTERN = new CancelMessage();

		@Override
		public boolean approve(final Object msg) {
			return msg == CANCEL;
		}

		@Override
		public <E extends Enum<E>> E type() { // unused
			return null;
		}
	}
}
